home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / sc_22.zip / CC1.C < prev    next >
C/C++ Source or Header  |  1988-06-14  |  22KB  |  803 lines

  1. /*
  2. ** Small-C Compiler -- Part 1 --  Top End.
  3. ** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix
  4. ** All rights reserved.
  5. */
  6.  
  7. #include <stdio.h>
  8. #include "notice.h"
  9. #include "cc.h"
  10.  
  11. /*
  12. ** miscellaneous storage
  13. */
  14. int
  15.   nogo,     /* disable goto statements? */
  16.   noloc,    /* disable block locals? */
  17.   opindex,  /* index to matched operator */
  18.   opsize,   /* size of operator in characters */
  19.   swactive, /* inside a switch? */
  20.   swdefault,/* default label #, else 0 */
  21.  *swnext,   /* address of next entry */
  22.  *swend,    /* address of last entry */
  23.  *stage,    /* staging buffer address */
  24.  *wq,       /* while queue */
  25.   argcs,    /* static argc */
  26.  *argvs,    /* static argv */
  27.  *wqptr,    /* ptr to next entry */
  28.   litptr,   /* ptr to next entry */
  29.   macptr,   /* macro buffer index */
  30.   pptr,     /* ptr to parsing buffer */
  31.   ch,       /* current character of input line */
  32.   nch,      /* next character of input line */
  33.   declared, /* # of local bytes to declare, -1 when declared */
  34.   iflevel,  /* #if... nest level */
  35.   skiplevel,/* level at which #if... skipping started */
  36.   nxtlab,   /* next avail label # */
  37.   litlab,   /* label # assigned to literal pool */
  38.   csp,      /* compiler relative stk ptr */
  39.   argstk,   /* function arg sp */
  40.   argtop,   /* highest formal argument offset */
  41.   ncmp,     /* # open compound statements */
  42.   errflag,  /* true after 1st error in statement */
  43.   eof,      /* true on final input eof */
  44.   output,   /* fd for output file */
  45.   files,    /* true if file list specified on cmd line */
  46.   filearg,  /* cur file arg index */
  47.   input   = EOF, /* fd for input file */
  48.   input2  = EOF, /* fd for "#include" file */
  49.   usexpr  = YES, /* true if value of expression is used */
  50.   ccode   = YES, /* true while parsing C code */
  51.  *snext,    /* next addr in stage */
  52.  *stail,    /* last addr of data in stage */
  53.  *slast,    /* last addr in stage */
  54.   listfp,   /* file pointer to list device */
  55.   lastst,   /* last parsed statement type */
  56.   oldseg;   /* current segment (0, DATASEG, CODESEG) */
  57.  
  58. char
  59.   optimize, /* optimize output of staging buffer? */
  60.   alarm,    /* audible alarm on errors? */
  61.   monitor,  /* monitor function headers? */
  62.   pause,    /* pause for operator on errors? */
  63.  *symtab,   /* symbol table */
  64.  *litq,     /* literal pool */
  65.  *macn,     /* macro name buffer */
  66.  *macq,     /* macro string buffer */
  67.  *pline,    /* parsing buffer */
  68.  *mline,    /* macro buffer */
  69.  *line,     /* ptr to pline or mline */
  70.  *lptr,     /* ptr to current character in "line" */
  71.  *glbptr,   /* global symbol table */
  72.  *locptr,   /* next local symbol table entry */
  73.   quote[2] = {'"'}, /* literal string for '"' */
  74.  *cptr,     /* work ptrs to any char buffer */
  75.  *cptr2,
  76.  *cptr3,
  77.   msname[NAMESIZE],   /* macro symbol name */
  78.   ssname[NAMESIZE];   /* static symbol name */
  79.  
  80. int op[16] = {   /* p-codes of signed binary operators */
  81.   OR12,                        /* level5 */
  82.   XOR12,                       /* level6 */
  83.   AND12,                       /* level7 */
  84.   EQ12,   NE12,                /* level8 */
  85.   LE12,   GE12,  LT12,  GT12,  /* level9 */
  86.   ASR12,  ASL12,               /* level10 */
  87.   ADD12,  SUB12,               /* level11 */
  88.   MUL12, DIV12, MOD12          /* level12 */
  89.   };
  90.  
  91. int op2[16] = {  /* p-codes of unsigned binary operators */
  92.   OR12,                        /* level5 */
  93.   XOR12,                       /* level6 */
  94.   AND12,                       /* level7 */
  95.   EQ12,   NE12,                /* level8 */
  96.   LE12u,  GE12u, LT12u, GT12u, /* level9 */
  97.   ASR12,  ASL12,               /* level10 */
  98.   ADD12,  SUB12,               /* level11 */
  99.   MUL12u, DIV12u, MOD12u       /* level12 */
  100.   };
  101.  
  102. /*
  103. ** execution begins here
  104. */
  105. main(argc, argv) int argc, *argv; {
  106.   fputs(VERSION, stderr);
  107.   fputs(CRIGHT1, stderr);
  108.   argcs   = argc;
  109.   argvs   = argv;
  110.   swnext  = calloc(SWTABSZ, 1);
  111.   swend   = swnext+(SWTABSZ-SWSIZ);
  112.   stage   = calloc(STAGESIZE, 2*BPW);
  113.   wqptr   =
  114.   wq      = calloc(WQTABSZ, BPW);
  115.   litq    = calloc(LITABSZ, 1);
  116.   macn    = calloc(MACNSIZE, 1);
  117.   macq    = calloc(MACQSIZE, 1);
  118.   pline   = calloc(LINESIZE, 1);
  119.   mline   = calloc(LINESIZE, 1);
  120.   slast   = stage+(STAGESIZE*2*BPW);
  121.   symtab  = calloc((NUMLOCS*SYMAVG + NUMGLBS*SYMMAX), 1);
  122.   locptr  = STARTLOC;
  123.   glbptr  = STARTGLB;
  124.   
  125.   ask();          /* get user options */
  126.   openfile();     /* and initial input file */
  127.   preprocess();   /* fetch first line */
  128.   header();       /* intro code */
  129.   setcodes();     /* initialize code pointer array */ 
  130.   parse();        /* process ALL input */
  131.   trailer();      /* follow-up code */
  132.   fclose(output); /* explicitly close output */
  133.   }
  134.  
  135. /******************** high level parsing *******************/
  136.  
  137. /*
  138. ** process all input text
  139. **
  140. ** At this level, only static declarations,
  141. **      defines, includes and function
  142. **      definitions are legal...
  143. */
  144. parse() {
  145.   while (eof == 0) {
  146.     if     (amatch("extern", 6)) dodeclare(EXTERNAL);
  147.     else if(dodeclare(STATIC))   ;
  148.     else if( match("#asm"))      doasm();
  149.     else if( match("#include"))  doinclude();
  150.     else if( match("#define"))   dodefine();
  151.     else                         dofunction();
  152.     blanks();                 /* force eof if pending */
  153.     }
  154.   }
  155.  
  156. /*
  157. ** test for global declarations
  158. */
  159. dodeclare(class) int class; {
  160.   if     (amatch("char",     4))  declglb(CHR,  class);
  161.   else if(amatch("unsigned", 8)) {
  162.     if   (amatch("char",     4))  declglb(UCHR, class);
  163.     else {amatch("int",      3);  declglb(UINT, class);}
  164.     }
  165.   else if(amatch("int",      3)
  166.        || class == EXTERNAL)      declglb(INT,  class);
  167.   else return 0;
  168.   ns();
  169.   return 1;
  170.   }
  171.  
  172. /*
  173. ** declare a static variable
  174. */
  175. declglb(type, class)  int type, class; {
  176.   int id, dim;
  177.   while(1) {
  178.     if(endst()) return;  /* do line */
  179.     if(match("*"))       {id = POINTER;  dim = 0;}
  180.     else                 {id = VARIABLE; dim = 1;}
  181.     if(symname(ssname) == 0) illname();
  182.     if(findglb(ssname)) multidef(ssname);
  183.     if(id == VARIABLE) {
  184.       if     (match("("))  {id = FUNCTION; need(")");}
  185.       else if(match("["))  {id = ARRAY; dim = needsub();}
  186.       }
  187.     if     (class == EXTERNAL) external(ssname, type >> 2, id);
  188.     else if(   id != FUNCTION) initials(type >> 2, id, dim);
  189.     if(id == POINTER) 
  190.          addsym(ssname, id, type, BPW, 0, &glbptr, class);
  191.     else addsym(ssname, id, type, dim * (type >> 2), 0, &glbptr, class);
  192.     if(match(",") == 0) return;
  193.     }
  194.   }
  195.  
  196. /*
  197. ** initialize global objects
  198. */
  199. initials(size, ident, dim) int size, ident, dim; {
  200.   int savedim;
  201.   litptr = 0;
  202.   if(dim == 0) dim = -1;         /* *... or ...[] */
  203.   savedim = dim;
  204.   public(ident);
  205.   if(match("=")) {
  206.     if(match("{")) {
  207.       while(dim) {
  208.         init(size, ident, &dim);
  209.         if(match(",") == 0) break;
  210.         }
  211.       need("}");
  212.       }
  213.     else init(size, ident, &dim);
  214.     }
  215.   if(savedim == -1 && dim == -1) {
  216.     if(ident == ARRAY) error("need array size");
  217.     stowlit(0, size = BPW);
  218.     }
  219.   dumplits(size);
  220.   dumpzero(size, dim);           /* only if dim > 0 */
  221.   }
  222.  
  223. /*
  224. ** evaluate one initializer
  225. */
  226. init(size, ident, dim) int size, ident, *dim; {
  227.   int value;
  228.   if(string(&value)) {
  229.     if(ident == VARIABLE || size != 1)
  230.       error("must assign to char pointer or char array");
  231.     *dim -= (litptr - value);
  232.     if(ident == POINTER) point();
  233.     }
  234.   else if(constexpr(&value)) {
  235.     if(ident == POINTER) error("cannot assign to pointer");
  236.     stowlit(value, size);
  237.     *dim -= 1;
  238.     }
  239.   }
  240.  
  241. /*
  242. ** get required array size
  243. */
  244. needsub()  {
  245.   int val;
  246.   if(match("]")) return 0; /* null size */
  247.   if(constexpr(&val) == 0) val = 1;
  248.   if(val < 0) {
  249.     error("negative size illegal");
  250.     val = -val;
  251.     }
  252.   need("]");               /* force single dimension */
  253.   return val;              /* and return size */
  254.   }
  255.  
  256. /*
  257. ** open an include file
  258. */
  259. doinclude() {
  260.   int i; char str[30];
  261.   blanks();       /* skip over to name */
  262.   if(*lptr == '"' || *lptr == '<') ++lptr;
  263.   i = 0;
  264.   while(lptr[i]
  265.      && lptr[i] != '"'
  266.      && lptr[i] != '>'
  267.      && lptr[i] != '\n') {
  268.     str[i] = lptr[i];
  269.     ++i;
  270.     }
  271.   str[i] = NULL;
  272.   if((input2 = fopen(str,"r")) == NULL) {
  273.     input2 = EOF;
  274.     error("open failure on include file");
  275.     }
  276.   kill();   /* make next read come from new file (if open) */
  277.   }
  278.  
  279. /*
  280. ** define a macro symbol
  281. */
  282. dodefine() {
  283.   int k;
  284.   if(symname(msname) == 0) {
  285.     illname();
  286.     kill();
  287.     return;
  288.     }
  289.   k = 0;
  290.   if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0) == 0) {
  291.     if(cptr2 = cptr)
  292.       while(*cptr2++ = msname[k++]) ;
  293.     else {
  294.       error("macro name table full");
  295.       return;
  296.       }
  297.     }
  298.   putint(macptr, cptr+NAMESIZE, 2);
  299.   while(white()) gch();
  300.   while(putmac(gch()));
  301.   if(macptr >= MACMAX) {
  302.     error("macro string queue full");
  303.     abort(ERRCODE);
  304.     }
  305.   }
  306.  
  307. putmac(c)  char c; {
  308.   macq[macptr] = c;
  309.   if(macptr < MACMAX) ++macptr;
  310.   return c;
  311.   }
  312.  
  313. /*
  314. ** begin a function
  315. **
  316. ** called from "parse" and tries to make a function
  317. ** out of the following text
  318. */
  319. dofunction()  {
  320.   char *ptr;
  321.   nogo   =                      /* enable goto statements */
  322.   noloc  =                      /* enable block-local declarations */
  323.   lastst =                      /* no statement yet */
  324.   litptr = 0;                   /* clear lit pool */
  325.   litlab = getlabel();          /* label next lit pool */
  326.   locptr = STARTLOC;            /* clear local variables */
  327.   if(match("void")) blanks();   /* skip "void" & locate header */
  328.   if(monitor) lout(line, stderr);
  329.   if(symname(ssname) == 0) {
  330.     error("illegal function or declaration");
  331.     errflag = 0;
  332.     kill();                     /* invalidate line */
  333.     return;
  334.     }
  335.   if(ptr = findglb(ssname)) {   /* already in symbol table? */
  336.     if(ptr[CLASS] == AUTOEXT)
  337.          ptr[CLASS] = STATIC;
  338.     else multidef(ssname);
  339.     }
  340.   else addsym(ssname, FUNCTION, INT, 0, 0, &glbptr, STATIC);
  341.   public(FUNCTION);
  342.   argstk = 0;                  /* init arg count */
  343.   if(match("(") == 0) error("no open paren");
  344.   while(match(")") == 0) {     /* then count args */
  345.     if(symname(ssname)) {
  346.       if(findloc(ssname)) multidef(ssname);
  347.       else {
  348.         addsym(ssname, 0, 0, 0, argstk, &locptr, AUTOMATIC);
  349.         argstk += BPW;
  350.         }
  351.       }
  352.     else {
  353.       error("illegal argument name");
  354.       skip();
  355.       }
  356.     blanks();
  357.     if(streq(lptr,")") == 0 && match(",") == 0)
  358.       error("no comma");
  359.     if(endst()) break;
  360.     }
  361.   csp = 0;                     /* preset stack ptr */
  362.   argtop = argstk+BPW;         /* account for the pushed BP */
  363.   while(argstk) {
  364.     if     (amatch("char",     4)) {doargs(CHR);  ns();}
  365.     else if(amatch("int",      3)) {doargs(INT);  ns();}
  366.     else if(amatch("unsigned", 8)) {
  367.       if   (amatch("char", 4))     {doargs(UCHR); ns();}
  368.       else {amatch("int", 3);       doargs(UINT); ns();}
  369.       }
  370.     else {error("wrong number of arguments"); break;}
  371.     }
  372.   gen(ENTER, 0);
  373.   statement();
  374.   if(lastst != STRETURN && lastst != STGOTO)
  375.     gen(RETURN, 0);
  376.   if(litptr) {
  377.     toseg(DATASEG);
  378.     gen(REFm, litlab);
  379.     dumplits(1);               /* dump literals */
  380.     }
  381.   }
  382.  
  383. /*
  384. ** declare argument types
  385. */
  386. doargs(type) int type; {
  387.   int id, sz;
  388.   char c, *ptr;
  389.   while(1) {
  390.     if(argstk == 0) return;           /* no arguments */
  391.     if(decl(type, POINTER, &id, &sz)) {
  392.       if(ptr = findloc(ssname)) {
  393.         ptr[IDENT] = id;
  394.         ptr[TYPE]  = type;
  395.         putint(sz, ptr+SIZE, 2);
  396.         putint(argtop-getint(ptr+OFFSET, 2), ptr+OFFSET, 2);
  397.         }
  398.       else error("not an argument");
  399.       }
  400.     argstk = argstk - BPW;            /* cnt down */
  401.     if(endst()) return;
  402.     if(match(",") == 0) error("no comma");
  403.     }
  404.   }
  405.  
  406. /*
  407. ** parse next local or argument declaration
  408. */
  409. decl(type, aid, id, sz) int type, aid, *id, *sz; {
  410.   int n, p;
  411.   if(match("(")) p = 1;
  412.   else           p = 0;
  413.   if(match("*"))        {*id = POINTER;  *sz  = BPW;}
  414.   else                  {*id = VARIABLE; *sz  = type >> 2;}
  415.   if((n = symname(ssname)) == 0) illname();
  416.   if(p && match(")")) ;
  417.   if(match("(")) {
  418.     if(!p || *id != POINTER) error("try (*...)()");
  419.     need(")");
  420.     }
  421.   else if(*id == VARIABLE && match("[")) {
  422.     *id = aid;
  423.     if((*sz *= needsub()) == 0) {
  424.       if(aid == ARRAY) error("need array size");
  425.       *sz  = BPW;      /* size of pointer argument */
  426.       }
  427.     }
  428.   return n;
  429.   }
  430.  
  431. /******************** start 2nd level parsing *******************/
  432.  
  433. /*
  434. ** statement parser
  435. */
  436. statement() {
  437.   if(ch == 0 && eof) return;
  438.   else if(amatch("char",     4)) {declloc(CHR);    ns();}
  439.   else if(amatch("int",      3)) {declloc(INT);    ns();}
  440.   else if(amatch("unsigned", 8)) {
  441.     if   (amatch("char",     4)) {declloc(UCHR);   ns();}
  442.     else {amatch("int",      3);  declloc(UINT);   ns();}
  443.     }
  444.   else {
  445.     if(declared >= 0) {
  446.       if(ncmp > 1) nogo = declared;   /* disable goto */
  447.       gen(ADDSP, csp - declared);
  448.       declared = -1;
  449.       }
  450.     if(match("{"))                 compound();
  451.     else if(amatch("if",       2)) {doif();           lastst = STIF;}
  452.     else if(amatch("while",    5)) {dowhile();        lastst = STWHILE;}
  453.     else if(amatch("do",       2)) {dodo();           lastst = STDO;}
  454.     else if(amatch("for",      3)) {dofor();          lastst = STFOR;}
  455.     else if(amatch("switch",   6)) {doswitch();       lastst = STSWITCH;}
  456.     else if(amatch("case",     4)) {docase();         lastst = STCASE;}
  457.     else if(amatch("default",  7)) {dodefault();      lastst = STDEF;}
  458.     else if(amatch("goto",     4)) {dogoto();         lastst = STGOTO;}
  459.     else if(dolabel())                                lastst = STLABEL;
  460.     else if(amatch("return",   6)) {doreturn(); ns(); lastst = STRETURN;}
  461.     else if(amatch("break",    5)) {dobreak();  ns(); lastst = STBREAK;}
  462.     else if(amatch("continue", 8)) {docont();   ns(); lastst = STCONT;}
  463.     else if(match(";"))            errflag = 0;
  464.     else if(match("#asm"))         {doasm();          lastst = STASM;}
  465.     else                           {doexpr(NO); ns(); lastst = STEXPR;}
  466.     }
  467.   return lastst;
  468.   }
  469.  
  470. /*
  471. ** declare local variables
  472. */
  473. declloc(type)  int type;  {
  474.   int id, sz;
  475.   if(swactive)     error("not allowed in switch");
  476.   if(noloc)        error("not allowed with goto");
  477.   if(declared < 0) error("must declare first in block");
  478.   while(1) {
  479.     if(endst()) return;
  480.     decl(type, ARRAY, &id, &sz);
  481.     declared += sz;
  482.     addsym(ssname, id, type,  sz, csp - declared, &locptr, AUTOMATIC);
  483.     if(match(",") == 0) return;
  484.     }
  485.   }
  486.  
  487. compound()  {
  488.   int savcsp;
  489.   char *savloc;
  490.   savcsp = csp;
  491.   savloc = locptr;
  492.   declared = 0;           /* may now declare local variables */
  493.   ++ncmp;                 /* new level open */
  494.   while (match("}") == 0)
  495.     if(eof) {
  496.       error("no final }");
  497.       break;
  498.       }
  499.     else statement();     /* do one */
  500.   if(--ncmp               /* close current level */
  501.   && lastst != STRETURN
  502.   && lastst != STGOTO)
  503.     gen(ADDSP, savcsp);   /* delete local variable space */
  504.   cptr = savloc;          /* retain labels */
  505.   while(cptr < locptr) {
  506.     cptr2 = nextsym(cptr);
  507.     if(cptr[IDENT] == LABEL) {
  508.       while(cptr < cptr2) *savloc++ = *cptr++;
  509.       }
  510.     else cptr = cptr2;
  511.     }
  512.   locptr = savloc;        /* delete local symbols */
  513.   declared = -1;          /* may not declare variables */
  514.   }
  515.  
  516. doif()  {
  517.   int flab1, flab2;
  518.   test(flab1 = getlabel(), YES);  /* get expr, and branch false */
  519.   statement();                    /* if true, do a statement */
  520.   if(amatch("else", 4) == 0) {    /* if...else ? */
  521.     /* simple "if"...print false label */
  522.     gen(LABm, flab1);
  523.     return;                       /* and exit */
  524.     }
  525.   flab2 = getlabel();
  526.   if(lastst != STRETURN && lastst != STGOTO)
  527.     gen(JMPm, flab2);
  528.   gen(LABm, flab1);    /* print false label */
  529.   statement();         /* and do "else" clause */
  530.   gen(LABm, flab2);    /* print true label */
  531.   }
  532.  
  533. dowhile()  {
  534.   int wq[4];              /* allocate local queue */
  535.   addwhile(wq);           /* add entry to queue for "break" */
  536.   gen(LABm, wq[WQLOOP]);  /* loop label */
  537.   test(wq[WQEXIT], YES);  /* see if true */
  538.   statement();            /* if so, do a statement */
  539.   gen(JMPm, wq[WQLOOP]);  /* loop to label */
  540.   gen(LABm, wq[WQEXIT]);  /* exit label */
  541.   delwhile();             /* delete queue entry */
  542.   }
  543.  
  544. dodo() {
  545.   int wq[4];
  546.   addwhile(wq);
  547.   gen(LABm, wq[WQLOOP]);
  548.   statement();
  549.   need("while");
  550.   test(wq[WQEXIT], YES);
  551.   gen(JMPm, wq[WQLOOP]);
  552.   gen(LABm, wq[WQEXIT]);
  553.   delwhile();
  554.   ns();
  555.   }
  556.  
  557. dofor() {
  558.   int wq[4], lab1, lab2;
  559.   addwhile(wq);
  560.   lab1 = getlabel();
  561.   lab2 = getlabel();
  562.   need("(");
  563.   if(match(";") == 0) {
  564.     doexpr(NO);           /* expr 1 */
  565.     ns();
  566.     }
  567.   gen(LABm, lab1);
  568.   if(match(";") == 0) {
  569.     test(wq[WQEXIT], NO); /* expr 2 */
  570.     ns();
  571.     }
  572.   gen(JMPm, lab2);
  573.   gen(LABm, wq[WQLOOP]);
  574.   if(match(")") == 0) {
  575.     doexpr(NO);           /* expr 3 */
  576.     need(")");
  577.     }
  578.   gen(JMPm, lab1);
  579.   gen(LABm, lab2);
  580.   statement();
  581.   gen(JMPm, wq[WQLOOP]);
  582.   gen(LABm, wq[WQEXIT]);
  583.   delwhile();
  584.   }
  585.  
  586. doswitch() {
  587.   int wq[4], endlab, swact, swdef, *swnex, *swptr;
  588.   swact = swactive;
  589.   swdef = swdefault;
  590.   swnex = swptr = swnext;
  591.   addwhile(wq);
  592.   *(wqptr + WQLOOP - WQSIZ) = 0;
  593.   need("(");
  594.   doexpr(YES);                /* evaluate switch expression */
  595.   need(")");
  596.   swdefault = 0;
  597.   swactive = 1;
  598.   gen(JMPm, endlab = getlabel());
  599.   statement();                /* cases, etc. */
  600.   gen(JMPm, wq[WQEXIT]);
  601.   gen(LABm, endlab);
  602.   gen(SWITCH, 0);             /* match cases */
  603.   while(swptr < swnext) {
  604.     gen(NEARm, *swptr++);
  605.     gen(WORDn,  *swptr++);    /* case value */
  606.     }
  607.   gen(WORDn, 0);
  608.   if(swdefault) gen(JMPm, swdefault);
  609.   gen(LABm, wq[WQEXIT]);
  610.   delwhile();
  611.   swnext    = swnex;
  612.   swdefault = swdef;
  613.   swactive  = swact;
  614.   }
  615.  
  616. docase() {
  617.   if(swactive == 0) error("not in switch");
  618.   if(swnext > swend) {
  619.     error("too many cases");
  620.     return;
  621.     }
  622.   gen(LABm, *swnext++ = getlabel());
  623.   constexpr(swnext++);
  624.   need(":");
  625.   }
  626.  
  627. dodefault() {
  628.   if(swactive) {
  629.     if(swdefault) error("multiple defaults");
  630.     }
  631.   else error("not in switch");
  632.   need(":");
  633.   gen(LABm, swdefault = getlabel());
  634.   }
  635.  
  636. dogoto() {
  637.   if(nogo > 0) error("not allowed with block-locals");
  638.   else noloc = 1;
  639.   if(symname(ssname)) gen(JMPm, addlabel(NO));
  640.   else error("bad label");
  641.   ns();
  642.   }
  643.  
  644. dolabel() {
  645.   char *savelptr;
  646.   blanks();
  647.   savelptr = lptr;
  648.   if(symname(ssname)) {
  649.     if(gch() == ':') {
  650.       gen(LABm, addlabel(YES));
  651.       return 1;
  652.       }
  653.     else bump(savelptr-lptr);
  654.     }
  655.   return 0;
  656.   }
  657.  
  658. addlabel(def) int def; {
  659.   if(cptr = findloc(ssname)) {
  660.     if(cptr[IDENT] != LABEL) error("not a label");
  661.     else if(def) {
  662.       if(cptr[TYPE]) error("duplicate label");
  663.       else cptr[TYPE] = YES;
  664.       }
  665.     }
  666.   else cptr = addsym(ssname, LABEL, def, 0, getlabel(), &locptr, LABEL);
  667.   return (getint(cptr+OFFSET, 2));
  668.   }
  669.  
  670. doreturn()  {
  671.   int savcsp;
  672.   if(endst() == 0) doexpr(YES);
  673.   savcsp = csp;
  674.   gen(RETURN, 0);
  675.   csp = savcsp;
  676.   }
  677.  
  678. dobreak()  {
  679.   int *ptr;
  680.   if((ptr = readwhile(wqptr)) == 0) return;
  681.   gen(ADDSP, ptr[WQSP]);
  682.   gen(JMPm, ptr[WQEXIT]);
  683.   }
  684.  
  685. docont()  {
  686.   int *ptr;
  687.   ptr = wqptr;
  688.   while (1) {
  689.     if((ptr = readwhile(ptr)) == 0) return;
  690.     if(ptr[WQLOOP]) break;
  691.     }
  692.   gen(ADDSP, ptr[WQSP]);
  693.   gen(JMPm, ptr[WQLOOP]);
  694.   }
  695.  
  696. doasm()  {
  697.   ccode = 0;           /* mark mode as "asm" */
  698.   while (1) {
  699.     inline();
  700.     if(match("#endasm")) break;
  701.     if(eof)break;
  702.     fputs(line, output);
  703.     }
  704.   kill();
  705.   ccode = 1;
  706.   }
  707.  
  708. doexpr(use) int use; {
  709.   int const, val;
  710.   int *before, *start;
  711.   usexpr = use;        /* tell isfree() whether expr value is used */
  712.   while(1) {
  713.     setstage(&before, &start);
  714.     expression(&const, &val);
  715.     clearstage(before, start);
  716.     if(ch != ',') break;
  717.     bump(1);
  718.     }
  719.   usexpr = YES;        /* return to normal value */
  720.   }
  721.  
  722. /******************** miscellaneous functions *******************/
  723.  
  724. /*
  725. ** get run options
  726. */
  727. ask() {
  728.   int i;
  729.   i = listfp = nxtlab = 0;
  730.   output = stdout;
  731.   optimize = YES;
  732.   alarm = monitor = pause = NO;
  733.   line = mline;
  734.   while(getarg(++i, line, LINESIZE, argcs, argvs) != EOF) {
  735.     if(line[0] != '-' && line[0] != '/') continue;
  736.     if(toupper(line[1]) == 'L'
  737.     && isdigit(line[2])
  738.     && line[3] <= ' ') {
  739.       listfp = line[2]-'0';
  740.       continue;
  741.       }
  742.     if(toupper(line[1]) == 'N'
  743.     && toupper(line[2]) == 'O'
  744.     && line[3] <= ' ') {
  745.       optimize = NO;
  746.       continue;
  747.       }
  748.     if(line[2] <= ' ') {
  749.       if(toupper(line[1]) == 'A') {alarm   = YES; continue;}
  750.       if(toupper(line[1]) == 'M') {monitor = YES; continue;}
  751.       if(toupper(line[1]) == 'P') {pause   = YES; continue;}
  752.       }
  753.     fputs("usage: cc [file]... [-m] [-a] [-p] [-l#] [-no]\n", stderr);
  754.     abort(ERRCODE);
  755.     }
  756.   }
  757.  
  758. /*
  759. ** input and output file opens
  760. */
  761. openfile() {        /* entire function revised */
  762.   char outfn[15];
  763.   int i, j, ext;
  764.   input = EOF;
  765.   while(getarg(++filearg, pline, LINESIZE, argcs, argvs) != EOF) {
  766.     if(pline[0] == '-' || pline[0] == '/') continue;
  767.     ext = NO;
  768.     i = -1;
  769.     j = 0;
  770.     while(pline[++i]) {
  771.       if(pline[i] == '.') {
  772.         ext = YES;
  773.         break;
  774.         }
  775.       if(j < 10) outfn[j++] = pline[i];
  776.       }
  777.     if(!ext) strcpy(pline + i, ".C");
  778.     input = mustopen(pline, "r");
  779.     if(!files && iscons(stdout)) {
  780.       strcpy(outfn + j, ".ASM");
  781.       output = mustopen(outfn, "w");
  782.       }
  783.     files = YES;
  784.     kill();
  785.     return;
  786.     }
  787.   if(files++) eof = YES;
  788.   else input = stdin;
  789.   kill();
  790.   }
  791.  
  792. /*
  793. ** open a file with error checking
  794. */
  795. mustopen(fn, mode) char *fn, *mode; {
  796.   int fd;
  797.   if(fd = fopen(fn, mode)) return fd;
  798.   fputs("open error on ", stderr);
  799.   lout(fn, stderr);
  800.   abort(ERRCODE);
  801.   }
  802.  
  803.